package org.fastsyncer.manager.listener;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.fastsyncer.common.DefaultThreadFactory;
import org.fastsyncer.common.constant.ConnectorConstant;
import org.fastsyncer.common.constant.MappingConstant;
import org.fastsyncer.common.entity.MappingTask;
import org.fastsyncer.manager.driver.impl.AbstractDriverEvent;
import org.fastsyncer.manager.framework.DataFactory;
import org.fastsyncer.manager.listener.ldap.LdapListener;
import org.fastsyncer.manager.listener.mysql.MysqlListener;
import org.fastsyncer.manager.listener.mysql.SqlMysqlListener;
import org.fastsyncer.manager.listener.oracle.OracleListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public final class ListenerFactory extends AbstractDriverEvent {

    private static final Logger logger = LoggerFactory.getLogger(ListenerFactory.class);

    private static volatile ListenerFactory instance = null;

    public static ListenerFactory getInstance() {
        if (null == instance) {
            synchronized (ListenerFactory.class) {
                if (null == instance) {
                    instance = new ListenerFactory();
                }
            }
        }
        return instance;
    }

    // 定义任务处理线程池,当第执行二个任务时,第一个任务完成,会复用线程,不会新建线程,执行结束一段时间会自动回收
    private static final ExecutorService SERVICE = Executors.newCachedThreadPool(new DefaultThreadFactory("ListenerFactory-threadpool"));
    
    // 缓存监听实例
    private static final Map<String, LifecycleListener> CACHE = new ConcurrentHashMap<>();

    private DataFactory data = DataFactory.getInstance();
    
    /**
     * 热加载启动
     * @Title: start 
     * @Description: 程序启动的时候加载启动的驱动
     * @return: void
     */
    public synchronized void start() {
        Map<String, Object> mappings = data.getMappings();
        for (Map.Entry<String, Object> object : mappings.entrySet()) {
            MappingTask task = (MappingTask) object.getValue();
            // 是否满足驱动增量任务条件
            if (validateEnabled(task)) {
                this.start(task.getId());
            }
        }
    }
    
    @Override
    public void start(String id) {
        // 获取驱动
        MappingTask mapping = data.getMapping(id);
        if (null == mapping) {
            logger.error("The driver id can not be null:" + id);
            return;
        }
        // 检查是否已有监听
        if(null != CACHE.get(id)){
            return;
        }
        
        // 检查是否满足增量配置
        if (!validateEnabled(mapping)) {
            return;
        }
        // 获取驱动类型
        String connector = mapping.getSourceMapping().getConnector();
        LifecycleListener listener = null;
        switch (connector) {
        case ConnectorConstant.MYSQL_CONNECTOR:
            listener = new MysqlListener().setDriverId(id);
            break;
        case ConnectorConstant.ORACLE_CONNECTOR:
            listener = new OracleListener().setDriverId(id);;
            break;
        case ConnectorConstant.LDAP_CONNECTOR:
            listener = new LdapListener().setDriverId(id);
            break;
        case ConnectorConstant.SQLSERVER_CONNECTOR:
            break;
        case ConnectorConstant.SQL_MYSQL_CONNECTOR:
            listener = new SqlMysqlListener().setDriverId(id);
            break;
        case ConnectorConstant.SQL_ORACLE_CONNECTOR:
            break;
        default:
            break;
        }

        // 拿到监听
        if (null != listener) {
            try {
                // 放入缓存
                CACHE.put(id, listener);
                // 提交任务到线程池
                SERVICE.submit(listener);
            } catch (Exception exc) {
                logger.error("ListenerManager>handle: " + exc.getLocalizedMessage());
            }
        }
    }

    @Override
    public void stop(String id) {
        // 从缓存获取监听实例
        LifecycleListener listener = CACHE.get(id);
        if (null != listener) {
            // 关闭该监听
            listener.onClose();
            // 清楚缓存
            CACHE.remove(id);
            // 从缓存删除监听配置
            data.removeMappingMeta(id);
            // 输出提示,并结束此方法
            logger.info("The listener has been closed successfully." + id);
        }
    }

    /**
     * 是否满足驱动增量任务条件
     * @param task MappingTask
     * @return false/true
     */
    public boolean validateEnabled(MappingTask task) {
        try {
            String connector = task.getSourceMapping().getConnector();
            // 1.排除WebService连接器
            if (ConnectorConstant.WS_CONNECTOR.equals(connector)) {
                return false;
            }
            // 2.排除已禁用的驱动
            if (!task.isEnable()) {
                return false;
            }
            // 3.排除空策略集合
            Map<String, Map<String, String>> po = task.getPolicy();
            if (null == po) {
                return false;
            }
            // 4.排除空增量策略
            Map<String, String> inc = po.get(MappingConstant.POLICY_INCREMENT);
            if (null == inc) {
                return false;
            }
            // 5.排除非log模式
            if (!MappingConstant.POLICY_INCREMENT_MODEL_LOG.equals(inc.get("model"))) {
                return false;
            }
            // 6.排除未开启
            if (!Boolean.valueOf(inc.get("enable"))) {
                return false;
            }
            return true;
        } catch (Exception e) {
        }
        return false;
    }
}
